想知道nm命令的实现原理吗 | 您所在的位置:网站首页 › nm 无符号 › 想知道nm命令的实现原理吗 |
在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是:
nm objfile
objdump -x objfile (或其他选项)
readelf -a objfile
但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。这里针对AIX平台介绍附件中的代码所使用的方法来实现该功能。 附件中的C++代码巧妙利用了AIX提供的系统调用来读出ELF文件的符号表,它以面向对象的方式提供了如下接口: class XCOFFParser; //void * is SCNHDR * for 32 bit and SCNHDR_64 for 64 bit. //Return 0, contiue. Return 1: break the current parse. typedef int (*SectionCallback)(void *param, XCOFFParser *parser, int iIndex, void *secHeader); //void * is SYMENT * for 32 bit and SYMENT_64 for 64 bit. //Return 0, contiue. Return 1: break the current parse. typedef int (*SymbolCallback)(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry); enum XCOFF_SECTION{SECTION_TEXT=0, SECTION_DATA, SECTION_BSS, SECTION_DEBUG, SECTION_LOADER}; struct SectionInfo { XCOFF_SECTION sectionType; int sectionNum; char sectionName[MAX_SECTION_NAME_LENGTH]; }; class XCOFFParser { public: XCOFFParser(char *fileName) { strcpy(m_strFileName, fileName); m_ldPointer = NULL; m_bIs64 = 0; m_lSections = m_lSymbols = 0; memset(m_sections, -1, sizeof(m_sections)); } virtual ~XCOFFParser(); int InitParser(); int ParseSections(SectionCallback pfnCallback, void *param, int iIncludeDep=0); int ParseSymbols(SymbolCallback pfnCallback, void *param, int iIncludeDep=0); int DeinitParser(); int Is64Bit() { return m_bIs64; } char *GetFileName(char *buf) const { strcpy(buf, m_strFileName); return buf; } long GetSectionsNumber() const { return m_lSections; } long GetSymbolsNumber() const { return m_lSymbols; } int IsDebugSymbol(void *symEntry) { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == N_DEBUG; } return ((SYMENT *)symEntry)->n_scnum == N_DEBUG; } int IsABSSymbol(void *symEntry) { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == N_ABS; } return ((SYMENT *)symEntry)->n_scnum == N_ABS; } int IsUndefSymbol(void *symEntry) { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == N_UNDEF; } return ((SYMENT *)symEntry)->n_scnum == N_UNDEF; } int IsDefinedSymbol(void *symEntry) { int iInMem = (m_bIs64? ((SYMENT_64 *)symEntry)->n_sclass C_BLOCK:((SYMENT *)symEntry)->n_sclass C_BLOCK); return !IsDebugSymbol(symEntry) && !IsABSSymbol(symEntry) && !IsUndefSymbol(symEntry) && iInMem; } int IsTextSymbol(void *symEntry)//Functions' symbol { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum; } return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum; } int IsDataSymbol(void *symEntry)//data symbol { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum; } return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum; } int IsBssSymbol(void *symEntry) { if(m_bIs64) { return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum; } return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum; } /* int IsDebugSymbol(SYMENT *symEntry) { return symEntry->n_scnum == m_sections[SECTION_DEBUG].sectionNum; } */ protected: char m_strFileName[MAX_PATH_LEN]; LDFILE* m_ldPointer; int m_bIs64; long m_lSections, m_lSymbols; SectionInfo m_sections[MAX_SECTIONS]; }; 示例程序: #include #include "xcoff_parser.h" static int SymbolReadDefinedFuncs(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry) { //printf("In callback\n"); if(strlen(symName) > 0 && parser->IsDefinedSymbol(symEntry) && parser->IsTextSymbol(symEntry)) { //It's a function definition, let's store it into the map printf("Defined function name:%s, address:%p\n", symName, parser->Is64Bit()? ((SYMENT_64 *)symEntry)->n_value: ((SYMENT *)symEntry)->n_value); } return 0; } int main(int argc, char *argv[]) { XCOFFParser parser(buf); int ret = parser.InitParser(); if(ret != ERROR_XCOFF_SUCCESS) { printf("XCOFFParser::InitParser failed:%d.\n", ret); return ret; } ret = parser.ParseSections(NULL, NULL); if(ret != ERROR_XCOFF_SUCCESS) { printf("XCOFFParser::ParseSections failed:%d.\n", ret); return ret; } ret = parser.ParseSymbols(SymbolReadDefinedFuncs, NULL); if(ret != ERROR_XCOFF_SUCCESS) { printf("XCOFFParser::ParseSymbols failed:%d.\n", ret); return ret; } return 0; }xcoff_parser中所使用到的主要系统调用: LDFILE *ldopen( char *, LDFILE * ); int ldfhread( LDFILE *, void * ); int ldshread( LDFILE *, unsigned short, void * ); int ldtbread( LDFILE *, int, void * ); int ldclose( LDFILE * ); xcoff_parser.zip当看完下面这本书之后,你会发现你也可以实现这个功能: 《返璞归真--UNIX技术内幕》 |
CopyRight 2018-2019 实验室设备网 版权所有 |